package cn.edu.sdju.fengguoyu.ahoedgemonitor;

import cn.edu.sdju.fengguoyu.logger.Logger;
import cn.edu.sdju.fengguoyu.po.ServiceInfoTableRow;
import cn.edu.sdju.fengguoyu.proto.ServicesDetail;
import cn.edu.sdju.fengguoyu.proto.ServicesDetailList;
import cn.edu.sdju.fengguoyu.util.AhoUtil;
import io.grpc.stub.StreamObserver;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URL;
import java.util.HashMap;
import java.util.Optional;
import java.util.ResourceBundle;

import org.xbill.DNS.*;


public class PrimaryController implements Initializable {
    static Logger logger = new Logger(PrimaryController.class);
    @FXML
    public Label statusLabel;
    @FXML
    public HBox toolbar;
    public VBox contextBox;
    public ListView<String> sideMenu;
    @FXML
    public Button settingBtn;
    public static HashMap<String, Node> cachedLayout = null;
    @FXML
    public TextArea logTextArea;
    static Image settingIcon = null;

    public  PrimaryController() {
        if (settingIcon == null) {
            try {
                settingIcon = new Image(new FileInputStream(new File(App.class.getResource("setting.png").getFile())));
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static Node loadLayout(String url) throws IOException {
        if (cachedLayout.containsKey(url)) {
            logger.log("Used cached");
            return cachedLayout.get(url);
        } else {
            Node root = new FXMLLoader(App.class.getResource( url+".fxml")).load();
            cachedLayout.put(url, root);
            return root;
        }
    }
    public static Node loadLayout(String url, String alis) throws IOException {
        if (cachedLayout.containsKey(alis)) {
            logger.log("Used cached");
            return cachedLayout.get(alis);
        } else {
            Node root = new FXMLLoader(App.class.getResource( url+".fxml")).load();
            cachedLayout.put(alis, root);
            return root;
        }
    }
    public static Node loadLayoutWithoutCached(String url) throws IOException {
        return new FXMLLoader(App.class.getResource( url+".fxml")).load();
    }
    private void  replaceLayout(String layout) {
        try {
            contextBox.getChildren().clear();
            contextBox.getChildren().add(loadLayout(layout));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        if (cachedLayout == null) {
            cachedLayout = new HashMap<>();
        }
        App.logTextArea = logTextArea;
        ObservableList<String> side = FXCollections.observableArrayList("首页", "服务器列表", "用户列表");
        sideMenu.setItems(side);
        sideMenu.getStyleClass().add("my-list");
        sideMenu.getSelectionModel().select(0);
        replaceLayout("canvas_map");
        sideMenu.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, newValue) -> {
            switch (newValue.intValue()) {
                case 0:
                    App.stopDraw = false;
                    replaceLayout("canvas_map");
                    break;
                case 1:
                    App.stopDraw = true;
                    contextBox.getChildren().clear();
                    try {
                        contextBox.getChildren().add(loadLayoutWithoutCached("service_table"));
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    break;
                case 2:
                    App.stopDraw = true;
                    replaceLayout("user_table");
                    break;
            }
        });
        MenuBar menuBar = new MenuBar();
        Menu openMenu = new Menu("连接");
        menuBar.getMenus().add(openMenu);
        MenuItem newConnectionItem = new MenuItem("新建连接");
        MenuItem disconnectItem = new MenuItem("断开当前连接");
        newConnectionItem.setOnAction(event -> {
            Dialog<InetSocketAddress> dialog = DialogBuilder.newSocketAddressDialog();
            Optional<InetSocketAddress> socketAddressOptional = dialog.showAndWait();
            socketAddressOptional.ifPresent((InetSocketAddress socketAddress) -> {
                logger.log(socketAddress.getHostName());
                String address = AhoUtil.customResolver(socketAddress.getHostName());
                App.getApp().rpcThread = new RPCThread(address, socketAddress.getPort());
            });
            if (App.getApp().rpcThread == null)
                return;
            App.getApp().rpcThread.getServerList("avoid", new StreamObserver<>() {
                @Override
                public void onNext(ServicesDetailList value) {
                    ServiceInfoTableRow row = new ServiceInfoTableRow(0,"-REG-",String.format("%s:%d", App.getApp().rpcThread.ipAddress, App.getApp().rpcThread.port),"OK");
                    row.setType("REG");
                    App.getApp().serviceInfoTableRowObservableList.add(
                            row
                    );
                    for (ServicesDetail servicesDetail : value.getServicesList()
                    ) {
                        ServiceInfoTableRow _s = new ServiceInfoTableRow(servicesDetail.getId(), servicesDetail.getNamed(), String.format("%s:%d", servicesDetail.getIpAddress(), servicesDetail.getPort()), "OK");
                        _s.setType(servicesDetail.getType());
                        _s.setType(servicesDetail.getType());
                        App.getApp().serviceInfoTableRowObservableList.add(
                                _s
                        );

                    }
                }

                @Override
                public void onError(Throwable t) {
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            statusLabel.setText("【与注册中心状态】无法建立连接");
                        }
                    });
                }

                @Override
                public void onCompleted() {
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            statusLabel.setText("【与注册中心状态】已连接");
                            statusLabel.getStyleClass().add("status-green");
                            disconnectItem.setDisable(false);

                        }
                    });
                }
            });
            App.getApp().rpcThread.registerObserver();

        });
        disconnectItem.setOnAction(event -> {
            App.getApp().rpcThread.disconnect();
            statusLabel.getStyleClass().clear();
            statusLabel.setText("【与注册中心状态】已断开连接");
            disconnectItem.setDisable(true);
            App.getApp().serviceInfoTableRowObservableList.clear();
            App.getApp().connections.clear();
            App.getApp().sprites.clear();
        });
        disconnectItem.setDisable(true);

        Menu debugMenu = new Menu("Debug");
        MenuItem addOneLine = new MenuItem("AddOne");
        MenuItem addMockNode = new MenuItem("NewMockNode");
        addOneLine.setOnAction(event -> {
            logTextArea.appendText("XXXXXXXXXXXXXXXXXXXXXX\n");
        });
        debugMenu.getItems().add(addOneLine);
        menuBar.getMenus().add(debugMenu);
        openMenu.getItems().add(newConnectionItem);
        openMenu.getItems().add(disconnectItem);
        toolbar.getChildren().add(menuBar);
        ImageView view = new ImageView(settingIcon);
        view.setSmooth(true);
        view.setFitWidth(18.0);
        view.setFitHeight(18.0);
        settingBtn.setGraphic(view);
        settingBtn.setCursor(Cursor.HAND);
        settingBtn.setOnAction(event -> {
            Stage newStage = new Stage();
            Scene newScene = null;
            try {
                newScene = new Scene((Parent) PrimaryController.loadLayoutWithoutCached("setting_windows"));
                newScene.getStylesheets().add(App.class.getResource("css/main.css").toExternalForm());
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            newStage.setResizable(false);
            newStage.setMaximized(false);
            newStage.setScene(newScene);
            newStage.getIcons().add(settingIcon);
            newStage.setTitle("设置");
            newStage.show();
        });
    }


}
